﻿using Autofac;
using Common;
using DBContext;
using EV.EventBus;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZoneLine.Common;
using ZoneLine.Models;
using ZoneLine.Models.PackageModel;
using ZoneLine.Printers;

namespace ZoneLine.Stations
{
    public class QOP050RStation : WorkStationDBase
    {
        public QOP050RStation()
        {
        }

        public void Init(string ip, int port, string startAddr, string endUploadCodeAddr, string endUploadDataAddr, string allowWorkAddr, string printerName)
        {
            Ip = ip;
            Port = port;
            _startAddr = startAddr;
            _readLength = 514;

            _printerName = printerName;

            EndUpLoadCodeAddr = endUploadCodeAddr;
            EndUpLoadDataAddr = endUploadDataAddr;
            AllowWorkAddr = allowWorkAddr;
            StationRecordData = new QOP050RStationResult();
            HeartToPlcAddr = "DB55.18.0";
            PrintRltAddr = "DB55.502";

            ResetPrintTriggerAddr = "DB55.506";

            WorkDirectionAddr = "DB55.508";

            TaskMaster.Default.AddCycleTask(nameof(QOP050RStation), 1, () =>
            {
                var value = (short)Cache.WorkDirection;
                WriteData(WorkDirectionAddr, value);
            }, false, EV.EventBus.CycleTask.TimeBaseEnum._1S);

            _logUiChannel = CurrentStationName + "uilog";
            MessageCenter.Subscribe(nameof(QOP050RStation), nameof(QOP050RStation), (e) =>
            {
                PrintLabel(false);
                return Task.CompletedTask;
            });
        }

        private string _printerName;

        private QOP050RStationResult _stationRecordData;

        public QOP050RStationResult StationRecordData
        {
            get { return _stationRecordData; }
            set => SetProperty(ref _stationRecordData, value);
        }

        #region 打印相关


        private short _triggerPrint;
        /// <summary>
        /// 触发打印
        /// </summary>
        public short TriggerPrint
        {
            get { return _triggerPrint; }
            set => SetProperty(ref _triggerPrint, value);
        }

        private int _index;
        /// <summary>
        /// 生产流水号
        /// </summary>
        public int Index
        {
            get { return _index; }
            set => SetProperty(ref _index, value);
        }

        private short _handSignalPrint;

        public short HandSignalPrint
        {
            get { return _handSignalPrint; }
            set { _handSignalPrint = value; }
        }

        /// <summary>
        /// 打印地址控制信息
        /// </summary>
        public string PrintRltAddr { get; set; }

        public string WorkDirectionAddr { get; set; }

        public string ResetPrintTriggerAddr { get; private set; }
        #endregion


        protected override void DealData(byte[] content)
        {
            StationRecordData.AbsScanCode = GetPlcString(content, 26);
            StationRecordData.NutScanCode = GetPlcString(content, 58);
            StationRecordData.PartType = GetPlcString(content, 90);
            StationRecordData.Result = GetPlcString(content, 102);

            StationRecordData.SpringCushionScanCode = GetPlcString(content, 150);
            StationRecordData.SpringScanCode = GetPlcString(content, 182);
            StationRecordData.NutScanCode2 = GetPlcString(content, 214);//螺母批次码2
            StationRecordData.ComponentScanCode = GetPlcString(content, 246);//合件批次码
            StationRecordData.DustCapScanCode = GetPlcString(content, 278);//防尘盖批次码

            StationRecordData.TightenTorque = _client.ByteTransform.TransSingle(content, 114);
            StationRecordData.TightenAngle = _client.ByteTransform.TransSingle(content, 118);
            StationRecordData.PressPosition = _client.ByteTransform.TransSingle(content, 122);
            StationRecordData.PressForce = _client.ByteTransform.TransSingle(content, 126);
            StationRecordData.CycleTime = _client.ByteTransform.TransSingle(content, 130);
            StationRecordData.ThreadLength = _client.ByteTransform.TransSingle(content, 510);

            TriggerPrint = _client.ByteTransform.TransInt16(content, 500);

            HandSignalPrint = _client.ByteTransform.TransInt16(content, 506);


            //Index = _client.ByteTransform.TransInt16(content, 504) + 5000;
        }

        protected override void DealWithSignal(string name)
        {
            if (name == nameof(StartUploadCode))
            {
                //todo 上传了条码 这时候验证是否要工作
                if (StartUploadCode == false)
                {
                    WriteData(EndUpLoadCodeAddr, false);
                    WriteData(AllowWorkAddr, 0);
                    return;
                }
                else
                {

                    #region 库存校验
                    var res = QOP50_CheckInventory(StationRecordData.NutScanCode2, StationRecordData.DustCapScanCode, StationRecordData.ComponentScanCode);
                    if (!res) return;
                    #endregion

                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位结论验证,条码信息是{StationRecordData.AbsScanCode}");
                    var validataRlt = Validata(CurrentStationName, StationRecordData.AbsScanCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位的验证结果是{validataRlt}");
                    var writeRlt = WriteWorkActionToPlc(AllowWorkAddr, validataRlt);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位向下位机下发消息，下发{writeRlt}");
                    return;
                }
            }

            if (name == nameof(StartUploadData))
            {
                if (StartUploadData)
                {
                    //todo 上传数据 这时候将数据记录到数据库中
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到记录数据命令");
                    var rlt = RecordData();
                    WriteData(EndUpLoadDataAddr, rlt == 1);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}记录数据完成");

                    #region 库存校验\扣减库存
                    var res = QOP50_DeductionQty(StationRecordData.NutScanCode2, StationRecordData.DustCapScanCode, StationRecordData.ComponentScanCode);
                    if (!res)
                    {
                        //todo 写入报警点位
                        //WriteData();
                    }
                    #endregion

                }
                else
                {
                    WriteData(EndUpLoadDataAddr, false);
                }
            }

            if (name == nameof(TriggerPrint))
            {
                if (TriggerPrint == 1 && HandSignalPrint == 0)
                {
                    PrintLabel();
                }
                else
                {
                    //   WriteData(PrintRltAddr, 0);
                }
                return;
            }
        }

        private void PrintLabel(bool needInc = true)
        {
            Index = ProductIndexHelper.GetIndex(Cache.Model, 5000, Cache.WorkDirection, WorkDirectionEnum.Right, needInc);
            WriteData(ResetPrintTriggerAddr, 1);
            LogWithUi(_logUiChannel, $"在{CurrentStationName}收到打印信息，打印第{Index}号工件");
            IPrinter printer = null;
            var config = ContainerServer.Container.Resolve<PrintConfigTotal>();
            var templatePath = string.Empty;
            switch (Cache.Model)
            {
                case ModelEnum.LX:
                    printer = new LXQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.LxqcConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.LxqcConfig.TemplatePathR;
                    }
                    break;
                case ModelEnum.SQ:
                    printer = new SQQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.Sqqc_Config.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.Sqqc_Config.TemplatePathR;
                    }
                    break;
                case ModelEnum.BQKH:
                    printer = new BQKHPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.BqqcKhConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.BqqcKhConfig.TemplatePathR;
                    }
                    break;
                case ModelEnum.BQLH:
                    printer = new BQLHPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.BqqcLHConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.BqqcLHConfig.TemplatePathR;
                    }
                    break;
                case ModelEnum.WL:
                    printer = new WLQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.WlqcConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.WlqcConfig.TemplatePathR;
                    }
                    break;
                default:
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到不存在对应的模板，打印失败");
                    break;
            }
            if (printer != null)
            {
                try
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}开始打印第【{Index}】工件，模板是【${templatePath}】");
                    var code = printer.PrintLabel(templatePath, _printerName, Index);
                    //打印成功，将数据打印的数据记录到关联表中
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}打印第{Index}工件、工件abs码【{StationRecordData.AbsScanCode}】完成");
                    var printRecord = new AbsPrintResult();
                    printRecord.Brand = Cache.Model.ToString();
                    printRecord.AbsCode = StationRecordData.AbsScanCode;
                    printRecord.Code = code;
                    printRecord.PrintTime = DateTime.Now;
                    var para = StationEnableConfig.GetPara();
                    printRecord.LeftRight = (int)Cache.WorkDirection;
                    _dal.AddModel(printRecord);
                    _dal.UpdateModel<QOP050RStationResult>(p => p.AbsScanCode == printRecord.AbsCode, p => new QOP050RStationResult { Code = code });
                    UpdateBeforeStationCode(printRecord.AbsCode, code);
                    WriteData(PrintRltAddr, 1);
                }
                catch (Exception ex)
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}打印失败,失败原因{ex.Message}");
                    WriteData(PrintRltAddr, 2);
                }
            }
        }


        protected override WorkActionEnum Validata(string currentStation, string code, string[] stations = null)
        {
            var stationIndex = Cache.WorkStationValidationList.IndexOf(currentStation);
            if (stationIndex == -1)
            {
                return WorkActionEnum.NoEnable;
            }
            if (stationIndex > 0)
            {
                //检测上一个站
                var beforeStationName = Cache.WorkStationValidationList[stationIndex - 1];

                if (beforeStationName == nameof(QOP050LStation))
                {
                    var stationLIndex = Cache.WorkStationValidationList.IndexOf(nameof(QOP050LStation));
                    if (stationLIndex == 0)
                    {
                        //上个工位是L工位，只验证是否在R工位是否做过

                        //检查当前工位
                        LogWithUi(_logUiChannel, $"在{currentStation}工位不存在上个工位，检查在本工位工作结论");
                        var checkResult = CheckCodeExistAndResult(currentStation, code);
                        if (checkResult == 1)
                        {
                            return WorkActionEnum.HasWorkInCurrent;

                        }
                        else
                        {
                            return WorkActionEnum.StartWork;
                        }

                    }
                    else
                    {

                        beforeStationName = Cache.WorkStationValidationList[stationLIndex - 1];
                    }
                }

                LogWithUi(_logUiChannel, $"在{currentStation}工位上一个启动的检查工位是{beforeStationName}");
                var checkRlt = CheckCodeExistAndResult(beforeStationName, code);
                LogWithUi(_logUiChannel, $"在{beforeStationName}工位检查{code}的结论是{checkRlt}");
                if (checkRlt == 1)
                {
                    LogWithUi(_logUiChannel, $"在上个工位{beforeStationName}工位检查{code}的结论是{checkRlt},开始检查是否在本工位{currentStation}结论");
                    var currentResult = CheckCodeExistAndResult(currentStation, code);
                    LogWithUi(_logUiChannel, $"在本工位{currentStation}工位检查{code}的结论是{currentResult}");
                    if (currentResult == 1)
                    {
                        return WorkActionEnum.HasWorkInCurrent;
                    }
                    else
                    {
                        return WorkActionEnum.StartWork;
                    }
                }
                else if (checkRlt == 2)
                {
                    return WorkActionEnum.WorkNgInBefore;
                }
                else
                {
                    return WorkActionEnum.NotWorkInBefore;
                }
            }
            else
            {
                //检查当前工位
                LogWithUi(_logUiChannel, $"在{currentStation}工位不存在上个工位，检查在本工位工作结论");
                var checkResult = CheckCodeExistAndResult(currentStation, code);
                if (checkResult == 1)
                {
                    return WorkActionEnum.HasWorkInCurrent;

                }
                else
                {
                    return WorkActionEnum.StartWork;
                }
            }
        }


        protected override int RecordData()
        {
            var result = StationRecordData;
            result.CreateTime = DateTime.Now;
            var writeRlt = false;
            if (_dal.CheckExist<QOP050RStationResult>(p => p.AbsScanCode == result.AbsScanCode))
            {
                var beforeRlt = _dal.GetModel<QOP050RStationResult>(p => p.AbsScanCode == result.AbsScanCode);
                result.Id = beforeRlt.Id;
                writeRlt = _dal.UpdateModelSuper<QOP050RStationResult>(p => p.AbsScanCode == result.AbsScanCode, result);
            }
            else
            {
                writeRlt = _dal.AddModel(result);

            }
            return writeRlt ? 1 : 2;
        }

        #region 库存相关
        
        /// <summary>
        /// 前减螺母拧紧2台设备，库存扣减共用
        /// </summary>
        /// <param name="nutBatchCode">螺母批次码</param>
        /// <param name="dustCoverBatchCode">防尘盖批次码</param>
        /// <param name="componentBatchCode">合件批次码</param>
        /// <returns></returns>
        protected bool QOP50_DeductionQty(string nutBatchCode, string dustCoverBatchCode, string componentBatchCode)
        {
            try
            {
                //nutBatchCode = "$P000000001010900638$V0018000040$L25031901$Q500$O4500125969$S80$E$N64";
                //dustCoverBatchCode = "$P000000001010900100$V0018000040$L25031100$Q300$O4500125969$S80$E$N64";
                //componentBatchCode = "$P000000001010900200$V0018000040$L25031200$Q500$O4500125969$S80$E$N64";
                var flag = QOP50_CheckInventory(StationRecordData.NutScanCode2, StationRecordData.DustCapScanCode, StationRecordData.ComponentScanCode);
                if (flag)
                {
                    // 创建参数
                    var parameters = new SqlParameter[]
                    {
                        new SqlParameter("@NutBatchCode", nutBatchCode),    //输入参数1-螺母批次码
                        new SqlParameter("@DustCoverBatchCode", dustCoverBatchCode),//输入参数2-防尘盖批次码
                        new SqlParameter("@ComponentBatchCode", componentBatchCode),  //输入参数3-合件批次码
                        new SqlParameter("@OutPutResult", SqlDbType.Bit)  //输出参数-返回结果
                        {
                            Direction = ParameterDirection.Output
                        }
                    };
                    //调用存储过程
                    var result = DbConfig.DbContext.Ado.ExecuteDataTable(CommandType.StoredProcedure, "InventoryDeduction", parameters);

                    bool res = (bool)parameters.FirstOrDefault(o => o.ParameterName == "@OutPutResult").Value;

                    //记录日志{_logUiChannel} {CurrentStationName}
                    Logger.Log.Info($"产品：{StationRecordData.Code}在{_logUiChannel}工位，库存扣减开始，螺母批次码：{nutBatchCode}，防尘盖批次码：{dustCoverBatchCode}，合件批次码：{componentBatchCode}，库存扣减结果：{res}");

                    return res;
                }
            }
            catch (Exception ex)
            {
                Logger.Log.Info($"产品：{StationRecordData.Code}在{_logUiChannel}工位，库存扣减开始，螺母批次码：{nutBatchCode}，防尘盖批次码：{dustCoverBatchCode}，合件批次码：{componentBatchCode}，库存扣减结果：error. {ex.Message}");
                //throw;
            }

            return false;
            
        }

        /// <summary>
        /// 库存校验
        /// </summary>
        /// <param name="nutBatchCode">螺母批次码</param>
        /// <param name="dustCoverBatchCode">防尘盖批次码</param>
        /// <param name="componentBatchCode">合件批次码</param>
        /// <returns></returns>
        protected bool QOP50_CheckInventory(string nutBatchCode, string dustCoverBatchCode, string componentBatchCode)
        {
            //nutBatchCode = "$P000000001010900638$V0018000040$L25031901$Q500$O4500125969$S80$E$N64";
            //dustCoverBatchCode = "$P000000001010900100$V0018000040$L25031100$Q300$O4500125969$S80$E$N64";
            //componentBatchCode = "$P000000001010900200$V0018000040$L25031200$Q500$O4500125969$S80$E$N64";

            var list = _dal.GetModelList<InventoryInfoModel>(o => o.MainBatchCode == nutBatchCode && o.MaterialType == eMaterialType.Nut && o.SurplusQty > 0);
            if (list.Count <= 0)
            {
                LogWithUi(_logUiChannel, $"在{CurrentStationName}校验螺母批次数量库存不足");
                //todo 写入报警点位
                WriteData("DB55.22", 1);
                return false;
            }

            list = _dal.GetModelList<InventoryInfoModel>(o => o.MainBatchCode == dustCoverBatchCode && o.MaterialType == eMaterialType.DustCover && o.SurplusQty > 0);
            if (list.Count <= 0)
            {
                LogWithUi(_logUiChannel, $"在{CurrentStationName}校验防尘盖批次数量库存不足");
                //todo 写入报警点位
                WriteData("DB55.22", 1);
                return false;
            }


            list = _dal.GetModelList<InventoryInfoModel>(o => o.MainBatchCode == componentBatchCode && o.MaterialType == eMaterialType.Component && o.SurplusQty > 0);
            if (list.Count <= 0)
            {
                LogWithUi(_logUiChannel, $"在{CurrentStationName}校验合件批次数量库存不足");
                //todo 写入报警点位
                WriteData("DB55.22", 1);
                return false;
            }

            //todo 消除报警点位
            WriteData("DB55.22", 0);

            return true;
        }
        
        #endregion
    }
}
